package workflow.util;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import workflow.model.ProcessNode;
import workflow.model.ProcessTransition;
import workflow.model.ProcessVariable;


public class XmlUtil {
	public List buildTask(String xml, Long processDefId, HashMap<String, String> variableMap, Long version){
		List list = new ArrayList();
		
		try{
			Document document = DocumentHelper.parseText(xml);
			Date today = new Date();
			list.addAll(this.buildStartOrEndNode(document, processDefId , today, version));
			list.addAll(this.buildTaskNode(new String[]{"task-node","decision","fork","join"},document, processDefId , today, version));
			list.addAll(this.buildTransition(document, processDefId, version));
			list.addAll(this.buildVariable(processDefId, variableMap, version));
		} catch (Exception e){
			e.printStackTrace();
		}
		
		return list;
	}
	
	private List<ProcessNode> buildStartOrEndNode(Document document, Long processDefId, Date today, Long version){
		List<ProcessNode> list = new ArrayList<ProcessNode>();
		
		Element root = document.getRootElement();
		Element node = root.element("start-state");
		String id = node.attributeValue("id");
		String name = node.attributeValue("name");
		String marker = node.attributeValue("marker");
		String billType = node.attributeValue("billtype");
		String percentPoint = node.attributeValue("perpoint");
		
		//start node
		ProcessNode task = new ProcessNode();
		task.setName(name);
		task.setNodeFlag(id);
		task.setNodeType("start-state");
		task.setStatus("0");
		task.setVisiable("0");
		task.setCreateDate(today);
		task.setProInsId(processDefId);
		task.setVersion(version.intValue());
		task.setPercentPoint(percentPoint);
		
		list.add(task);
		
		//end node
		node = root.element("end-state");
		id = node.attributeValue("id");
		name = node.attributeValue("name");
		marker = node.attributeValue("marker");
		billType = node.attributeValue("billtype");
		percentPoint = node.attributeValue("perpoint");
		
		task = new ProcessNode();
		task.setName(name);
		task.setNodeFlag(id);
		task.setNodeType("end-state");
		task.setStatus("0");
		task.setVisiable("0");
		task.setCreateDate(today);
		task.setProInsId(processDefId);
		task.setVersion(version.intValue());
		task.setPercentPoint(percentPoint);

		list.add(task);
		
		return list;
	}
		
	private List<ProcessNode> buildTaskNode(String[] nodeTypes, Document document, Long processDefId , Date today, Long version){
		List<ProcessNode> list = new ArrayList<ProcessNode>();
		Element root = document.getRootElement();
		Element node = null;
		Element subNode = null;
		ProcessNode task = null;
		String assignee = null;
		String assigneeExp = null;
		
		for(String nodeType : nodeTypes){
			Iterator<Element> it = root.elementIterator(nodeType);
			
			while(it.hasNext()){
				node = it.next();
				task = new ProcessNode();
				
				task.setCreateDate(today);
				//节点属性
				task.setName(node.attributeValue("name"));
				task.setNodeType(nodeType);
				task.setNodeFlag(node.attributeValue("id"));
				task.setExpression("undefined".equals(node.attributeValue("expr")) == true ? "" : node.attributeValue("expr"));
				task.setVisiable("0");
				task.setStatus("0");
				task.setVersion(version.intValue());
				task.setProInsId(processDefId);
				task.setPercentPoint("undefined".equals(node.attributeValue("perpoint")) == true ? "" : node.attributeValue("perpoint"));

				//子节点属性
				subNode = (Element)node.selectSingleNode("task/assignment");
				task.setFormUrl(subNode.attributeValue("cls"));
				
				subNode = (Element)node.selectSingleNode("work");
				assignee = subNode.attributeValue("actorid");
				assigneeExp = subNode.attributeValue("actorname");
				
				if(assignee != null && !"".equals(assignee.trim())){
					task.setAssignee(Long.valueOf(assignee));
				}
				if(assigneeExp != null && !"".equals(assigneeExp.trim())){
					task.setAssigneeExp(assigneeExp);
				}
				
				list.add(task);
			}
		}
		
		return list;
	}
	
	private List<ProcessTransition> buildTransition(Document document, Long processDefId, Long version){
		List<ProcessTransition> list = new ArrayList<ProcessTransition>();
		ProcessTransition pt = null;
		Element root = document.getRootElement();
		List<Element> eList = root.selectNodes("//transition");
		
		for(Element e : eList){
			pt = new ProcessTransition();
			
			pt.setName(e.attributeValue("name"));
			pt.setEndTaskFlag(e.attributeValue("to"));
			pt.setStartTaskFlag(e.attributeValue("from"));
			pt.setProInsId(processDefId);
			pt.setStatus("1");
			pt.setVersion(version.intValue());
			
			list.add(pt);
		}
	
		return list;
	}
	
	private List<ProcessVariable> buildVariable(Long processDefId, HashMap<String, String> variableMap, Long version){
		List<ProcessVariable> list = new ArrayList<ProcessVariable>();
		Set keys = variableMap.keySet();
		Iterator<String> it = keys.iterator();
		String key = null;
		String value = null;
		ProcessVariable var = null;
		
		while(it.hasNext()){
			key = it.next();
			value = variableMap.get(key);
			
			var = new ProcessVariable();
			var.setProInsId(processDefId);
			var.setVarName(key);
			var.setVarValue(value);
			var.setVersion(version.intValue());
			
			list.add(var);
		}
		
		return list;
	}
}
